#include<GL/glut.h>
#include<vector>
#include<iostream>
#include<deque>
#include<stdlib.h>
#include<ctime>
using namespace std;

#define HEIGHT 420  //3 eksigini kullanabiliyorsun  80 +  istenen oyun yuksekligi * 20 (18)
#define WIDTH 240   //2 eksigini kullanabiliyorsun  40 +  istenen oyun genisligi * 20	(10)
#define FPS 10
#define KEYFPS 75

vector<vector<int> > alan;
int h1=0,w1=0,ph1=0,pw1=0;
int h2=0,w2=0,ph2=0,pw2=0;
int h3=0,w3=0,ph3=0,pw3=0;
int h4=0,w4=0,ph4=0,pw4=0;
float sure = 0.0;
int score=0;
int mypause=0,dead=0;
int hiz=50;
int yikilan=0;
int keys[256]={0};
int flags[256]={0};
int newTurn=0;
int ifSquare=0;
int ifSquareCurrent=0;

void check(){
	int ctrl=0,tmpscr=0;
	for(unsigned int i=1;i<HEIGHT/20;i++){
		ctrl=0;
		for(unsigned int j=0;j<WIDTH/20;j++)
			if(alan[i][j]!=1) ctrl=1;
		if(ctrl==0){
			alan.erase(alan.begin()+i);
			vector<int> tmp;
			for(unsigned int k=0;k<WIDTH;k++)
				tmp.push_back(0);
			tmp[0]=1;
			tmp[WIDTH/20-1]=1;
			alan.push_back(tmp);
			tmpscr++;
			i--;
			yikilan++;
		}
	}
	score+=tmpscr*tmpscr*10;	
	if(yikilan>hiz/2){
		hiz--;	
		yikilan=0;
	}
}

void rect(int h, int w,int color)
{
	glBegin(GL_POLYGON);
	
	//RENKLER ICIN IF STATEMENTLARA BOL
	if(color==1) glColor3f(1.0,0.3,0.3);
	if(color==2) glColor3f(0.4,1.0,0.4);
	if(color==3) glColor3f(0.4,0.4,1.0);
	if(color==4) glColor3f(0.4,0.9,1.0);
	if(color==9) glColor3f(0.35,0.35,0.35);
	
	glVertex2d(w*20, h*20);
	glVertex2d(w*20+19, h*20);
	glVertex2d(w*20+19, h*20+19);
	glVertex2d(w*20, h*20+19);
	glEnd();
}

void randgen(){
	int tmp=0;
	tmp=rand()%7;
	h1=ph1;
	h2=ph2;
	h3=ph3;
	h4=ph4;
	w1=pw1;
	w2=pw2;
	w3=pw3;
	w4=pw4;
	
	//Down'a basili tutarken yeni gelen kaymasin hemencecik diye
	newTurn=0;
	//Kare rotate olmasin diye
	ifSquareCurrent=ifSquare;
	ifSquare=0;
	
	if(tmp==0){
		pw1=pw4=WIDTH/40-1;
		ph1=ph2=ph3=HEIGHT/20-3;
		pw2=WIDTH/40;
		pw3=WIDTH/40-2;
		ph4=HEIGHT/20-4;	
	}
	if(tmp==1){
		pw1=WIDTH/40-1;
		ph1=ph2=ph3=HEIGHT/20-3;
		pw2=WIDTH/40;
		pw3=pw4=WIDTH/40-2;
		ph4=HEIGHT/20-4;	
	}
	if(tmp==2){
		pw1=WIDTH/40-1;
		ph1=ph2=ph3=HEIGHT/20-3;
		pw2=pw4=WIDTH/40;
		pw3=WIDTH/40-2;
		ph4=HEIGHT/20-4;	
	}
	if(tmp==3){
		pw1=WIDTH/40-1;
		ph1=ph2=ph3=ph4=HEIGHT/20-3;
		pw4=WIDTH/40;
		pw3=WIDTH/40-2;
		pw2=WIDTH/40+1;
	}
	if(tmp==4){
		pw1=pw4=WIDTH/40-1;
		ph1=ph3=HEIGHT/20-3;
		ph2=ph4=HEIGHT/20-4;
		pw2=WIDTH/40;
		pw3=WIDTH/40-2;
	}
	if(tmp==5){
		pw1=pw4=WIDTH/40-1;
		ph1=ph2=HEIGHT/20-3;
		ph3=ph4=HEIGHT/20-4;
		pw2=WIDTH/40;
		pw3=WIDTH/40-2;
	}
	if(tmp==6){
		ifSquare=1;
		pw1=pw3=WIDTH/40-1;
		ph1=ph2=HEIGHT/20-3;
		pw2=pw4=WIDTH/40;
		ph3=ph4=HEIGHT/20-4;	
	}
	
	
	if(alan[h1][w1]==1||alan[h2][w2]==1||alan[h3][w3]==1||alan[h4][w4]==1) dead=1;
	else {
		dead=0;
		alan[h1][w1]=alan[h2][w2]=alan[h3][w3]=alan[h4][w4]=2;
	}
}

void up(){// ROTATIONLAR I HANDLE EDECEKSIN BURDA DA

	if(ifSquareCurrent)
		return;
	int tmph2,tmph3,tmph4,tmpw2,tmpw3,tmpw4;
	int th2,th3,th4,tw2,tw3,tw4;
	th2=h2-h1;
	th3=h3-h1;
	th4=h4-h1;
	tw2=w2-w1;
	tw3=w3-w1;
	tw4=w4-w1;
	
	tmph2=h1+th2*0-tw2*1;
	tmpw2=w1+th2*1+tw2*0;
	
	tmph3=h1+th3*0-tw3*1;
	tmpw3=w1+th3*1+tw3*0;
	
	tmph4=h1+th4*0-tw4*1;
	tmpw4=w1+th4*1+tw4*0;
	
	if(alan[tmph2][tmpw2]!=1 && alan[tmph3][tmpw3]!=1 && alan[tmph4][tmpw4]!=1){
		alan[h2][w2]=0;
		alan[h3][w3]=0;
		alan[h4][w4]=0;
		alan[h1][w1]=0;
		h2=tmph2;
		h3=tmph3;
		h4=tmph4;
		w2=tmpw2;
		w3=tmpw3;
		w4=tmpw4;
		alan[h1][w1]=2;
		alan[h2][w2]=2;
		alan[h3][w3]=2;
		alan[h4][w4]=2;
	}
}

void move(int x,int y){
	if(alan[h1+x][w1+y]!=1 && alan[h2+x][w2+y]!=1 && alan[h3+x][w3+y]!=1 && alan[h4+x][w4+y]!=1){
		alan[h1][w1]=0;
		alan[h2][w2]=0;
		alan[h3][w3]=0;
		alan[h4][w4]=0;
		h1+=x;
		h2+=x;
		h3+=x;
		h4+=x;
		w1+=y;
		w2+=y;
		w3+=y;
		w4+=y;
		alan[h1][w1]=2;
		alan[h2][w2]=2;
		alan[h3][w3]=2;
		alan[h4][w4]=2;
	}
	else if(x==-1 && y==0){
		alan[h1][w1]=1;
		alan[h2][w2]=1;
		alan[h3][w3]=1;
		alan[h4][w4]=1;
		check(); //YANAN SATIR OLDU MU OLMADI MI MUHABBETI
		randgen(); //YENI BIR SEKIL YARATIP POINTERLARINI VE HARITANI INITLIYCEK
	}
}

void board()
{
	char skor[50];
	sprintf(skor, "Score" );
	glColor3f(0.0,0.0, 0.0);
	glRasterPos2f(  20*WIDTH/19 -5   ,HEIGHT/9+30  );
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
	sprintf(skor, "%d", score );
	glRasterPos2f(  20*WIDTH/19+50 , HEIGHT/9+30 );
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
	sprintf(skor, "%.1f", sure);
	glRasterPos2f(20*WIDTH/19+50 , HEIGHT/9);
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
	sprintf(skor, "Time");
	glRasterPos2f(20*WIDTH/19-5 , HEIGHT/9);
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
	glColor3f(1.0,1.0,1.0);
	sprintf(skor, "Press P to PAUSE");
	glRasterPos2f(20*WIDTH/19-9, 7*HEIGHT/9);
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *p);
	sprintf(skor, "Press Q to QUIT");
	glRasterPos2f(20*WIDTH/19-9, 6*HEIGHT/9+25);
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *p);
	sprintf(skor, "Press R to RESTART");
	glRasterPos2f(20*WIDTH/19-9, 6*HEIGHT/9+5);
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *p);	
}

void pausescr()
{
	char skor[50];
	sprintf(skor, "PAUSED" );
	glColor3f(0.0,0.0, 0.0);
	glRasterPos2f(  WIDTH/4  ,HEIGHT/2  );
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *p);
	sprintf(skor, "Press P again");
	glRasterPos2f( WIDTH/4, HEIGHT/2-60);
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
	sprintf(skor, "to continue");
	glRasterPos2f( WIDTH/4, HEIGHT/2-80);
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
}

void deadscr()
{
	char skor[50];
	sprintf(skor, "DEAD" );
	glColor3f(0.0,0.0, 0.0);
	glRasterPos2f(  WIDTH/4  ,HEIGHT/2  );
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *p);
	sprintf(skor, "Press R to Restart");
	glRasterPos2f( WIDTH/4-5, HEIGHT/2-60);
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
	sprintf(skor, "Press Q to Quit");
	glRasterPos2f( WIDTH/4-5, HEIGHT/2-80);
	for (char *p = skor ; *p; p++)
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
}

void display()
{
	int i,j;
	glClear(GL_COLOR_BUFFER_BIT);
	
	for(i=HEIGHT/20-2; i<HEIGHT/20 ; i++)
		for(j=0;j<WIDTH/20;j++)
			rect(i,j,3);
			
	for(j=0;j<WIDTH/20;j++)
		rect(0,j,3);
		
	for(i=0; i<HEIGHT/20 ; i++){
		rect(i,0,3);
		rect(i,WIDTH/20-1,3);
	}
	
	if(dead==0){
		for(i=1;i<HEIGHT/20-2;i++)
			for(j=1;j<WIDTH/20-1;j++){
				if(alan[i][j]==1)rect(i,j,1);
				else if(alan[i][j]==2) rect(i,j,2);
			}
	}
	
	for(i=0;i<HEIGHT/20;i++)
		for(j=WIDTH/20;j<WIDTH/20+7;j++)
			rect(i,j,3);
	for(i=8;i<12;i++)
		for(j=12;j<18;j++)
			rect(i,j,9);
	for(i=14;i<17;i++)
		for(j=12;j<18;j++)
			rect(i,j,9);
	for(i=2;i<5;i++)
		for(j=12;j<18;j++)
			rect(i,j,9);
	if(dead==0&&mypause==0){
		rect(ph1-8,pw1+9,4);
		rect(ph2-8,pw2+9,4);
		rect(ph3-8,pw3+9,4);
		rect(ph4-8,pw4+9,4);	
	}
	board();
	
	if(dead==1) deadscr();
	if(mypause==1) pausescr();
	
	
	glutSwapBuffers();
	
}


void rstart(){


	int i=0,j=0;

	for(i=0;i<HEIGHT/20;i++)
		for(j=0;j<WIDTH/20;j++)
			alan[i][j]=0;
	for(i=0;i<WIDTH/20;i++)
		alan[0][i]=1;
	for(i=0;i<HEIGHT/20;i++){
		alan[i][WIDTH/20-1]=1;
		alan[i][0]=1;
	}
	
	sure = 0.0;
	score=0;
	mypause=0;
	dead=0;
	randgen();	
}

void keyboard(unsigned char key, int a, int b)
{
	if(mypause==0 && dead==0){
		switch(key)
		{	
			case 'q':
				exit(0);
				break;
			case 'Q':
				exit(0);
				break;
			case 'r':
				rstart();
				break;
			case 'R':
				rstart();
				break;
			case 'p':
				mypause=1;
				break;
			case 'P':
				mypause=1;
				break;
		}
	}
	else if(mypause==1){		
		switch(key)
		{
			case 'q':
				exit(0);
				break;
			case 'Q':
				exit(0);
				break;
			case 'r':
				rstart();
				break;
			case 'R':
				rstart();
				break;
			case 'p':
				mypause=0;
				break;
			case 'P':
				mypause=0;
				break;
		}
	}
	else if(dead==1){		
		switch(key)
		{
			case 'q':
				exit(0);
				break;
			case 'Q':
				exit(0);
				break;
			case 'r':
				rstart();
				break;
			case 'R':
				rstart();
				break;
		}
	}
		
	glutPostRedisplay();
}

void specialup(int key, int a, int b)	
{	keys[key]=0;
	flags[key]=0;}
void special(int key, int a, int b)
{
	if(mypause==0&&dead==0){
	
		if(key==GLUT_KEY_UP)
			up();
		if(key==GLUT_KEY_RIGHT)
			move(0,1);
		if(key==GLUT_KEY_LEFT)
			move(0,-1);;
		keys[key]=1;
		if(!flags[key])
			flags[key]=1;
	}
}

void fpstimer(int)
{
	if(mypause==0 && dead==0){
		sure+=0.01;
		if(!keys[GLUT_KEY_DOWN])
		{
			if(int(100*sure)%hiz==0)
				move(-1,0);	
		}
	}
	glutTimerFunc(FPS, fpstimer, 1);
	//glutPostRedisplay();
}
void timer(int)
{
	if(mypause==0&&dead==0){
		if(newTurn++>3)
			if(keys[GLUT_KEY_DOWN])
				move(-1,0);
		if(keys[GLUT_KEY_RIGHT])
		{
			if(flags[GLUT_KEY_RIGHT]<3)
				flags[GLUT_KEY_RIGHT]++;
			else
				move(0,1);
		}
		if(keys[GLUT_KEY_LEFT])
		{
			if(flags[GLUT_KEY_LEFT]<3)
				flags[GLUT_KEY_LEFT]++;
			else
				move(0,-1);
		}
	}			
	glutTimerFunc(KEYFPS, timer, 1);
	//glutPostRedisplay();
}
/*
void special(int key, int a, int b)
{
	if(mypause==0&&dead==0){
		switch (key)
		{
			case GLUT_KEY_UP:
					up();//move(-1,0);
					break;
			case GLUT_KEY_DOWN:
					move(-1,0);
					break;
			case GLUT_KEY_RIGHT:
					move(0,1);
					break;
			case GLUT_KEY_LEFT:
					move(0,-1);
					break;
		}
	}
	glutPostRedisplay();
}
*/
void initGL()
{
	int i=0,j=0;
	alan.resize(HEIGHT/20);
	for (i=0; i<HEIGHT/20;i++)
		alan[i].resize(WIDTH/20);
		
	for(i=0;i<HEIGHT/20;i++)
		for(j=0;j<WIDTH/20;j++)
			alan[i][j]=0;
	for(i=0;i<WIDTH/20;i++)
		alan[0][i]=1;
	for(i=0;i<HEIGHT/20;i++){
		alan[i][WIDTH/20-1]=1;
		alan[i][0]=1;
	}
	
	
	
	
	srand( time(NULL) );	
	cout << alan.size() << alan[1].size()<< endl;
	
	glViewport(0,0,WIDTH,HEIGHT);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, WIDTH+139,0,HEIGHT-1,-10,10);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glClearColor(0.3, 0.3, 0.3, 0.0);
}

int main(int argc,char *argv[])
{	
	
	glutInit(&argc,argv);
	glutInitWindowSize(WIDTH+140,HEIGHT);
	glutInitWindowPosition(100,100);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
	glutCreateWindow("Tetris by Cnsn");
	glutDisplayFunc(display);
	glutIdleFunc(display);
	glutKeyboardFunc(keyboard);
	glutSpecialFunc(special);
	glutSpecialUpFunc(specialup);
	initGL();
	
	randgen();
	randgen();
		
	glutTimerFunc(FPS, fpstimer, 1);
	glutTimerFunc(KEYFPS, timer, 1);
	glutMainLoop();

return 0;
}
